import { _decorator, Component, tween, TweenEasing } from 'cc';
import { CallBackHandler } from '../Model/PoolObj/CallBackHandler';
import { EasingType, TweenTarget } from '../../Game/Config/GameEnum';
import { MathUtil } from '../../Util/MathUtil';
const { ccclass, property } = _decorator;

@ccclass('LuckDraw')
export class LuckDraw extends Component {
  @property({ tooltip: '缓动曲线' })
  easing: string = EasingType.linear;
  @property({ tooltip: '总时间, 单位: 秒' })
  runTime: number = 1.5;
  @property({ tooltip: '转几圈' })
  circleNum: number = 3;
  @property({
    tooltip: '抽奖元素数量',
  })
  itemLength: number = 1;
  /** 抽奖列表 */
  private rollList: number[] = null!;

  /** 抽奖次数 */
  private rollTime: number = 0;
  /** 抽奖结果 */
  private rollResult: number[] = [];
  isSkip: boolean = false;
  isMove: boolean = false;
  drawChange: (index: number) => void;
  drawMove: (value: number) => void;

  private callback: CallBackHandler;
  private nowIndex: number = 0;

  protected onLoad(): void {
    this.rollList = Array.from({ length: this.itemLength }, (v, i) => i);
  }

  draw(count: number, callback: CallBackHandler) {
    if (count <= 0) throw new Error('抽奖次数不能小于0');
    const result = [];
    const temp = MathUtil.randomNumbers(0, this.itemLength, count);
    temp.forEach((ele) => {
      result.push(this.rollList[ele]);
    });
    if (this.isSkip) {
      callback.execute(result);
      return;
    }
    this.isMove = true;
    this.rollResult = result;
    this.callback = callback;
    this.rollTime = result.length;
    this.tempIndex = 0;
    this.doDraw();
  }

  setlist(list: number[]) {
    this.rollList = list;
    this.itemLength = list.length;
  }

  pushItem(index: number) {
    const temp = this.rollList.indexOf(index);
    if (temp > -1) return;
    this.rollList.push(index);
    this.rollList.sort((a, b) => a - b);
    this.itemLength = this.rollList.length;
  }

  private resultIndex: number = 0;
  private tempIndex: number = 0;
  private doDraw() {
    const result = this.rollResult[this.tempIndex];
    const resultIndex = this.rollList.indexOf(result);
    const temp = this.nowIndex <= resultIndex ? resultIndex - this.nowIndex : this.nowIndex - resultIndex + this.itemLength;
    this.resultIndex = temp + this.circleNum * this.itemLength;
    const target: TweenTarget = { number: this.nowIndex };
    tween(target)
      .to(
        this.runTime,
        { number: this.resultIndex },
        {
          easing: this.easing as TweenEasing,
          progress: (start: number, end: number, current: number, ratio: number): number => {
            const now = (start + Math.floor((end - start) * ratio)) % this.itemLength;
            if (now != this.nowIndex) {
              this.nowIndex = now;
              this.drawChange(this.rollList[this.nowIndex]);
            }
            if (this.drawMove) this.drawMove(current);
            return now;
          },
        }
      )
      .delay(0.5)
      .call(() => {
        this.nowIndex++;
        if (this.nowIndex < this.rollTime) {
          this.doDraw();
        } else {
          this.callback.execute(this.rollResult);
          this.callback = null;
          this.isMove = false;
        }
      })
      .start();
  }
}
